# app/utils/security.py
import secrets
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime, timedelta
import jwt
from functools import wraps
from flask import request, jsonify, current_app
from flask_socketio import emit
from flask_jwt_extended import get_jwt_identity, verify_jwt_in_request
from app.utils.response_utils import (
    success_response,
    error_response,
    ResponseCode
)



def generate_secure_token(length=32):
    """生成安全的随机令牌"""
    return secrets.token_urlsafe(length)


def hash_password(password):
    """生成密码哈希"""
    print(generate_password_hash(password))
    return generate_password_hash(password, method='pbkdf2:sha256')


def verify_password(hashed_password, password):
    """验证密码"""
    return check_password_hash(hashed_password, password)


def generate_jwt_token(user_id, expires_delta=None):
    """生成JWT访问令牌"""
    if expires_delta is None:
        expires_delta = timedelta(days=7)

    payload = {
        'sub': user_id,
        'exp': datetime.utcnow() + expires_delta,
        'iat': datetime.utcnow(),
        'type': 'access'
    }

    return jwt.encode(payload, current_app.config['SECRET_KEY'], algorithm='HS256')


def verify_jwt_token(token):
    """验证JWT令牌"""
    try:
        payload = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=['HS256'])
        user_id = payload.get('sub') or payload.get('identity')

        if not user_id:
            raise ValueError("Token中缺少用户ID")
        return str(user_id)  # 确保返回字符串格式
    except jwt.ExpiredSignatureError:
        return None
    except jwt.InvalidTokenError:
        return None

def token_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        from app import db
        token = None
        # 检查请求头中是否存在 token
        if 'Authorization' in request.headers:
            token = request.headers['Authorization']

        if not token:
            return error_response(code=ResponseCode.UNAUTHORIZED, message='未提供认证信息', http_code=401)
        try:
            # 解码 token
            currentUserId = verify_jwt_token(token)
            # 可以根据 userID 查询用户信息
        except Exception as e:
            print(e)
            return error_response(code=ResponseCode.INVALID_TOKEN, message='无效的令牌', http_code=403)

        return f(currentUserId, *args, **kwargs)  # 将当前用户ID传递给被装饰的函数
    return decorated_function


def socket_token_required(fn):
    @wraps(fn)
    def wrapper(*args, **kwargs):
        try:
            token = None

            # 1. 优先从查询参数获取 token
            token = request.args.get('token')

            # 2. 如果查询参数中没有，再尝试其他位置
            if not token:
                token = request.cookies.get('access_token_cookie')

            if not token:
                if len(args) > 0 and isinstance(args[0], dict):
                    token = args[0].get('token')

            # 验证流程保持不变
            if token:
                from flask_jwt_extended import decode_token
                current_user_id = verify_jwt_token(token)
                return fn(current_user_id,*args, **kwargs)
            else:
                print("No token found in any location")  # 调试输出
                return emit('error', {'code': ResponseCode.UNAUTHORIZED, 'message': 'Missing token'})
        except Exception as e:
            print(f"Socket token error: {e}")
            return emit('error', {'code': ResponseCode.UNAUTHORIZED, 'message': 'Invalid token'})

    return wrapper